package com.itmayiedu.main.threadpool.impl;

import com.itmayiedu.main.DBbean.DbBean;
import com.itmayiedu.main.threadpool.dao.IConnectionPool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

public class MyConnectionPool implements IConnectionPool {
    //配置信息
    private DbBean dbBean;
    //空间线程
    private BlockingQueue<Connection> freeConnection;
    //空间线程目前数量
    private AtomicInteger freeConnectionNum =new AtomicInteger(0);
    //活动线程
    private BlockingQueue<Connection> activeConnection ;


    public MyConnectionPool() {
        //初始化参数
        dbBean=DbBean.GetDbBean();
        freeConnection=new LinkedBlockingQueue<>(dbBean.getMaxConnections());
        activeConnection=new LinkedBlockingQueue<>(dbBean.getMaxActiveConnections());
    }

    /**
     * 将freeConnection空闲线程容器置入Connection对象
     * 初始化参数
     */
    private void  inif() throws Exception {
        //获取最大空闲线程数
       for (int i=0;i<dbBean.getMaxConnections();i++){
            Connection connection=newConnection();
            if (connection!=null) freeConnection.add(connection);
       }
    }

    // 创建Connection连接
    public  Connection newConnection() throws Exception {
        //门闩   作者认为任需要用到原子类，理由是在IsErrorNum中可能会出现脏读问题，导致错误信息抛出点不正确
        AtomicInteger errorNum =new AtomicInteger(0);
        Class.forName(dbBean.getDriverName());
        Connection connection = DriverManager.getConnection(dbBean.getUrl(), dbBean.getUserName(),
                dbBean.getPassword());
       connection=IsErrorNum(connection,errorNum);
        //原子类自增
        freeConnectionNum.getAndIncrement();
        return connection;
    }

    //报错机制
     Connection IsErrorNum(Connection connection,AtomicInteger errorNum) throws Exception {
        if (connection==null){
            errorNum.getAndIncrement();
            if (errorNum.get()>3){
                throw new Exception();
            }
            IsErrorNum(newConnection(),errorNum);
        }else {
            if (errorNum.get()>0) errorNum.getAndDecrement();
            return connection;
        }
        return null;
    }

    /**
     * 空闲线程存在，从空闲线程取出，放入活动线程中
     * 空闲线程不存在，新建一个Conection ，放入活动线程中
     * 由于是阻塞队列，所以我们只要定义queue的初始数量，queue会自动帮我们进行阻塞
     * @return
     */
    public Connection getConnection() throws Exception {
        //从空闲线程中拿
        if (freeConnection.size()>0){
            //自减
            freeConnectionNum.getAndDecrement();
            return freeConnection.poll();
        }else {
            //新建一个Connection,一直加到activeConnection活动线程中去
            Connection connection=newConnection();
            activeConnection.put(connection);
            return connection;
        }
    }

    /**
     * 先判断connnection是否已经关闭或者存活
     * 已经关闭和死亡的会被gc回收走所以过多做处理
     * 没有被关闭的优先考虑是否存入空闲线程中
     * @param connection
     */
    public void releaseConnection(Connection connection) throws SQLException, InterruptedException {
        if (connection==null||connection.isClosed()){
            if (freeConnectionNum.get()<dbBean.getMaxConnections()){
                freeConnection.put(connection);
                freeConnectionNum.getAndIncrement();
            }else {
                connection.close();
            }
            activeConnection.remove(connection);
        }else {
            System.gc();
        }
    }


}
